#include "Image.h"
#include<iostream>
Image::Image()
{
	tex = NULL;
	fbo = NULL;
	width = 0;
	height = 0;
}

Image::Image(int w, int h)
{
	tex = NULL;
	fbo = NULL;
	width = w;
	height = h;

	initFBO();
}

Image::Image(std::string path)
{
	tex = NULL;
	fbo = NULL;
	load(path);
}

Image::~Image(void)
{
	glDeleteFramebuffersEXT(1, &fbo);
	glDeleteRenderbuffersEXT(1, &depthBuffer);

	glDeleteTextures(1,&tex);
}

void Image::initFBO()
{
	glGenFramebuffersEXT(1, &fbo);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);


	glGenRenderbuffersEXT(1, &depthBuffer);
	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer);
	glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);



	glGenTextures(1, &tex);
	glBindTexture(GL_TEXTURE_2D, tex);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,  width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex, 0);


	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer);

	
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

}

void Image::load(std::string path)
{
	if(!tex && !fbo) //only load if it's empty and it's not setup for fbo
	{
		FREE_IMAGE_FORMAT formato = FreeImage_GetFileType(path.c_str(),0);
		FIBITMAP* imagen = FreeImage_Load(formato, path.c_str());
		FIBITMAP* temp = imagen;
		imagen = FreeImage_ConvertTo32Bits(imagen);
		FreeImage_Unload(temp);

		width = FreeImage_GetWidth(imagen);
		height = FreeImage_GetHeight(imagen);

		GLubyte* textura = new GLubyte[4*width*height];
		char* pixeles = (char*)FreeImage_GetBits(imagen);
		
		for(int j= 0; j<width*height; j++){
			textura[j*4+0]= pixeles[j*4+2];
			textura[j*4+1]= pixeles[j*4+1];
			textura[j*4+2]= pixeles[j*4+0];
			textura[j*4+3]= pixeles[j*4+3];
		}
		
		glGenTextures(1, &tex);
		glBindTexture(GL_TEXTURE_2D, tex);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA, width, height, 0, GL_RGBA,GL_UNSIGNED_BYTE,(GLvoid*)textura );
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		
		delete [] textura;
		glBindTexture(GL_TEXTURE_2D,0);
	}
}

int Image::getHeight()
{
	return height;
}
int Image::getWidth()
{
	return width;
}


void Image::enable()
{
	if(fbo)
	{
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

		glPushAttrib(GL_VIEWPORT_BIT);
		glViewport(0,0,width, height);

		GLint iViewport[4];
		glGetIntegerv( GL_VIEWPORT, iViewport );
		glMatrixMode(GL_PROJECTION);
		glPushMatrix();
		glLoadIdentity();
		glOrtho( iViewport[0], iViewport[0]+iViewport[2],
			iViewport[1]+iViewport[3], iViewport[1], -1000, 1000 );
		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();
		glLoadIdentity();

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glClearColor(0,0,0,0);
	}
}

void Image::disable()
{
	if(fbo)
	{
		glMatrixMode(GL_PROJECTION);
		glPopMatrix();
		glMatrixMode(GL_MODELVIEW);
		glPopMatrix();
		glPopAttrib();
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
	}
}


GLuint Image::getTextureID()
{
	return tex;
}

void Image::bind()
{
	glBindTexture(GL_TEXTURE_2D,tex);
}
void Image::draw(int x, int y, int width, int height, float shiftX, float shiftY, float angle)
{
	glBindTexture(GL_TEXTURE_2D,tex);
    glPushMatrix();
        glTranslated(x,y,0);
        glRotatef(angle+180,0,0,1);
        glScaled(width, height, 0);
        glBegin(GL_QUADS);
			glTexCoord2f(0.0f+shiftX,0.0f+ shiftY); glVertex3f(.5f,-.5f,0.0f);
			glTexCoord2f(0.0f+shiftX,1.0f+ shiftY); glVertex3f(.5f,.5f,0.0f);
			glTexCoord2f(1.0f+shiftX,1.0f+ shiftY); glVertex3f(-.5f,.5f,0.0f);
			glTexCoord2f(1.0f+shiftX,0.0f+ shiftY); glVertex3f(-.5f,-.5f,0.0f);
        glEnd();
	glPopMatrix();
	glBindTexture(GL_TEXTURE_2D,0);
}

void Image::draw(int x, int y)
{
	glBindTexture(GL_TEXTURE_2D,tex);
    glPushMatrix();
        glTranslated(x,y,0);
        glRotatef(180,0,0,1);
        glScaled(this->width, this->height, 0);
        glBegin(GL_QUADS);
			glTexCoord2f(0.0f,0.0f); glVertex3f(.5f,-.5f,0.0f);
			glTexCoord2f(0.0f,1.0f); glVertex3f(.5f,.5f,0.0f);
			glTexCoord2f(1.0f,1.0f); glVertex3f(-.5f,.5f,0.0f);
			glTexCoord2f(1.0f,0.0f); glVertex3f(-.5f,-.5f,0.0f);
        glEnd();
	glPopMatrix();
	glBindTexture(GL_TEXTURE_2D,0);
}

void Image::draw(int x, int y, float rotation)
{
	glBindTexture(GL_TEXTURE_2D,tex);
    glPushMatrix();
        glTranslated(x,y,0);
        glRotatef(rotation+180,0,0,1);
        glScaled(this->width, this->height, 0);
        glBegin(GL_QUADS);
			glTexCoord2f(0.0f,0.0f); glVertex3f(.5f,-.5f,0.0f);
			glTexCoord2f(0.0f,1.0f); glVertex3f(.5f,.5f,0.0f);
			glTexCoord2f(1.0f,1.0f); glVertex3f(-.5f,.5f,0.0f);
			glTexCoord2f(1.0f,0.0f); glVertex3f(-.5f,-.5f,0.0f);
        glEnd();
	glPopMatrix();
	glBindTexture(GL_TEXTURE_2D,0);
}

void Image::draw(int x, int y, int width, int height)
{
	glBindTexture(GL_TEXTURE_2D,tex);
    glPushMatrix();
        glTranslated(x,y,0);
        glRotatef(180,0,0,1);
        glScaled(width, height, 0);
        glBegin(GL_QUADS);
			glTexCoord2f(0.0f,0.0f); glVertex3f(.5f,-.5f,0.0f);
			glTexCoord2f(0.0f,1.0f); glVertex3f(.5f,.5f,0.0f);
			glTexCoord2f(1.0f,1.0f); glVertex3f(-.5f,.5f,0.0f);
			glTexCoord2f(1.0f,0.0f); glVertex3f(-.5f,-.5f,0.0f);
        glEnd();
	glPopMatrix();
	glBindTexture(GL_TEXTURE_2D,0);
}

void Image::draw(int x, int y, int width, int height, float rotation)
{
	glBindTexture(GL_TEXTURE_2D,tex);
    glPushMatrix();
        glTranslated(x,y,0);
        glRotatef(rotation+180,0,0,1);
        glScaled(width, height, 0);
        glBegin(GL_QUADS);
			glTexCoord2f(0.0f,0.0f); glVertex3f(.5f,-.5f,0.0f);
			glTexCoord2f(0.0f,1.0f); glVertex3f(.5f,.5f,0.0f);
			glTexCoord2f(1.0f,1.0f); glVertex3f(-.5f,.5f,0.0f);
			glTexCoord2f(1.0f,0.0f); glVertex3f(-.5f,-.5f,0.0f);
        glEnd();
	glPopMatrix();
	glBindTexture(GL_TEXTURE_2D,0);
}







void Image::draw(int x, int y, Shader* s)
{
	glBindTexture(GL_TEXTURE_2D,tex);
    glPushMatrix();
        glTranslated(x,y,0);
        glRotatef(180,0,0,1);
        glScaled(this->width, this->height, 0);
		s->enable();
        glBegin(GL_QUADS);
			glTexCoord2f(0.0f,0.0f); glVertex3f(.5f,-.5f,0.0f);
			glTexCoord2f(0.0f,1.0f); glVertex3f(.5f,.5f,0.0f);
			glTexCoord2f(1.0f,1.0f); glVertex3f(-.5f,.5f,0.0f);
			glTexCoord2f(1.0f,0.0f); glVertex3f(-.5f,-.5f,0.0f);
        glEnd();
		s->disable();
	glPopMatrix();
	glBindTexture(GL_TEXTURE_2D,0);
}